Imports BikiSoft.DataStream

Namespace Controls
    Public Class BarContainer
        Implements IStreamRecieve, IStreamConfig, IDisposable

        Private mName As String = ""
        Private WithEvents mStreamItems As New KeyedStringCollectionWithEvents

        Private WithEvents mBarSettings As New BarContainerSettingCollection

        ' Private mDataRefreshTime As Integer
        Private mDataRefreshBuffer As Stream = Nothing
        Private WithEvents mDataRefreshTimer As New System.Timers.Timer

        Sub New()

            ' This call is required by the Windows Form Designer.
            InitializeComponent()

            ' Add any initialization after the InitializeComponent() call.
            Me.Name = "Bar Gauge Holder"

            If mBarSettings.UpdateRate > 0 Then
                mDataRefreshTimer.Interval = mBarSettings.UpdateRate
            End If

        End Sub

        Sub New(ByVal Name As String)
            MyBase.New()

            Me.InitializeComponent()

            Me.Name = Name
        End Sub

#Region "Menu Functions/Events"

        Private Sub mBarSettings_AfterSet(ByVal sender As Object, ByVal e As KeyedCollectionWithEventsArgs(Of BarContainerSetting)) Handles mBarSettings.AfterSet
            If e.Item.Visible Then
                Me.InitialiseBar(e.Item)
            ElseIf Me.uxFlow.Controls.ContainsKey(e.Item.Name) Then
                Me.RemoveBar(e.Item.Name)
            End If
        End Sub

        Private Sub mBarSettings_AfterInsert(ByVal sender As Object, ByVal e As KeyedCollectionWithEventsArgs(Of BarContainerSetting)) Handles mBarSettings.AfterInsert
            If e.Item.Visible AndAlso Not Me.uxFlow.Controls.ContainsKey(e.Item.Name) Then
                Me.InitialiseBar(e.Item)
            End If
        End Sub

        Private Sub mBarSettings_AfterClear(ByVal sender As Object, ByVal e As System.EventArgs) Handles mBarSettings.AfterClear
            For Each ctrl As Control In uxFlow.Controls
                RemoveBar(ctrl.Name)
            Next
        End Sub



        '''' <summary>
        '''' Handles an item being Added
        '''' </summary>
        '''' <param name="sender"></param>
        '''' <param name="e"></param>
        '''' <remarks></remarks>
        'Private Sub AfterInsert(ByVal sender As Object, ByVal e As KeyedCollectionWithEventsArgs(Of String)) Handles mStreamItems.AfterInsert
        '    ' Initialise a control
        '    'InitialiseBar(e.Item)
        '    If mBarSettings.Contains(e.Item) Then
        '        mBarSettings(e.Item).Visible = True
        '    Else
        '        mBarSettings.Add(New BarContainerSetting(e.Item, Color.Blue, True))
        '    End If

        '    'If Not Me.mStreamItems.Contains(e.Item) Then
        '    '    InitialiseValidItem(e.Item)
        '    'End If
        'End Sub

        '''' <summary>
        '''' Handles an item being Removed
        '''' </summary>
        '''' <param name="sender"></param>
        '''' <param name="e"></param>
        '''' <remarks></remarks>
        'Private Sub BeforeRemove(ByVal sender As Object, ByVal e As KeyedCollectionWithEventsArgs(Of String)) Handles mStreamItems.AfterRemove
        '    ' Remove the control
        '    RemoveBar(e.Item)
        'End Sub

        ''' <summary>
        ''' Handles the items being cleared out
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub AfterClear(ByVal sender As Object, ByVal e As System.EventArgs) Handles mStreamItems.AfterClear
            ' Clear the controls
            'For Each Control As Controls.gaugeBar In Me.uxFlow.Controls
            '    Control.Dispose()
            'Next
            'Me.uxFlow.Controls.Clear()
        End Sub

        Private Sub InitialiseBar(ByRef Setting As BarContainerSetting)
            Dim Control As New Controls.gaugeBar(Setting.Name, Setting.Colour)
            Me.uxFlow.Controls.Add(Control)
            ' Check if the menu contains the key.. if so check it!
            'If Me.uxDisplayMenu.Items.ContainsKey(Name) Then
            '    CType(Me.uxDisplayMenu.Items(Name), ToolStripMenuItem).Checked = True
            'End If

            AddHandler Control.RequestRefresh, AddressOf PassRequestRefresh
        End Sub

        Private Sub RemoveBar(ByRef Name As String)
            Dim Control As Controls.gaugeBar = Me.uxFlow.Controls(Name)
            RemoveHandler Control.RequestRefresh, AddressOf PassRequestRefresh
            Me.uxFlow.Controls.RemoveByKey(Name)
            Control.Dispose()
        End Sub

        ''' <summary>
        ''' Passes the request to re-fresh the gauge down to whatever
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub PassRequestRefresh(ByVal sender As Object, ByVal e As System.EventArgs)
            RaiseEvent RequestRefresh(sender, e)
        End Sub

        Public Sub RecieveStream(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveStream
            If Not MyBase.IsDisposed AndAlso Not TimerRequired(Stream) Then
                For Each Control As Control In Me.uxFlow.Controls
                    Try
                        Dim Iface As IStreamRecieve = CType(Control, DataStream.IStreamRecieve) 'Control.GetType.GetInterface("IStreamRecieve")

                        ' Go thru each control and send the stream to it
                        If Not IsNothing(Iface) Then
                            Iface.RecieveStream(Stream)
                        End If
                    Catch ex As InvalidCastException

                    End Try
                Next
            End If
        End Sub

        Private Function TimerRequired(ByVal Item As Stream) As Boolean
            If mDataRefreshTimer.Enabled Then
                mDataRefreshBuffer = Item
                Return True
            Else
                If Not MyBase.IsDisposed Then
                    If mBarSettings.UpdateRate > 0 Then mDataRefreshTimer.Start()
                End If
                Return False
            End If
        End Function

        Private Sub TimerElapse(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) Handles mDataRefreshTimer.Elapsed
            mDataRefreshTimer.Stop()

            If Not IsNothing(Me.mDataRefreshBuffer) Then
                Me.RecieveStream(Me.mDataRefreshBuffer)
                mDataRefreshBuffer = Nothing
            End If
        End Sub

        Public Event RequestRefresh(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.RequestRefresh

        Public Event Restrict(ByVal sender As Object, ByVal e As DataStream.StreamRestrictEventArgs) Implements DataStream.IStreamRecieve.Restrict

        Public Event Seek(ByVal sender As Object, ByVal e As DataStream.StreamSeekEventArgs) Implements DataStream.IStreamRecieve.Seek

        Private Sub RefreshItems()
            If mBarSettings.UpdateRate > 0 Then
                mDataRefreshTimer.Interval = mBarSettings.UpdateRate
            End If
            For Each setting As BarContainerSetting In Me.mBarSettings
                If setting.Visible Then
                    If Not Me.uxFlow.Controls.ContainsKey(setting.Name) Then
                        Me.InitialiseBar(setting)
                    Else
                        CType(Me.uxFlow.Controls(setting.Name), gaugeBar).Colour = setting.Colour
                    End If
                Else
                    If Me.uxFlow.Controls.ContainsKey(setting.Name) Then
                        Me.RemoveBar(setting.Name)
                    End If
                End If
            Next
        End Sub

        Public Sub InitialiseValidItems(ByVal Items() As String) Implements DataStream.IStreamConfig.InitialiseValidItems
            ' Me.uxDisplayMenu.Items.Clear()
            If Not IsNothing(Items) AndAlso Items.Length > 0 Then
                For i As Integer = 0 To Items.Length - 1
                    If Items(i) Is Nothing Then
                        Debug.Print("NOTHING!!")
                    Else
                        InitialiseValidItem(Items(i))
                    End If

                Next
            End If
        End Sub

        Private Sub InitialiseValidItem(ByVal Name As String)

            If Not mBarSettings.Contains(Name) Then
                mBarSettings.Add(New BarContainerSetting(Name, Color.Blue))
            End If

            'Dim item As New ToolStripMenuItem(Name, Nothing, AddressOf menu_SelectItem)
            'item.Tag = Name
            'If mStreamItems.Contains(Name) Then
            '    item.Checked = True
            'End If
            'If Not Me.uxDisplayMenu.Items.ContainsKey(Name) Then
            '    Me.uxDisplayMenu.Items.Add(item)
            'End If
        End Sub

        Private Sub uxFlow_ControlAdded(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles uxFlow.ControlAdded, uxFlow.ControlRemoved
            Dim flox As FlowLayoutPanel = CType(sender, FlowLayoutPanel)
            If flox.Controls.Count > 0 Then
                Dim control As Control = flox.Controls(flox.Controls.Count - 1)
                Dim calcWidth As Integer = control.Location.X + control.Size.Width + 2
                If Me.MaximumSize.Width >= calcWidth AndAlso Me.MinimumSize.Width <= calcWidth Then
                    Me.Size = New Size(control.Location.X + control.Size.Width, Me.Size.Height)
                ElseIf calcWidth < Me.MinimumSize.Width Then
                    Me.Size = New Size(Me.MinimumSize.Width, Me.Size.Height)
                End If
            End If
        End Sub
#End Region

#Region "Properites"
        Public ReadOnly Property Items() As KeyedStringCollectionWithEvents Implements IStreamConfig.StreamControlItems
            Get
                Return mStreamItems
            End Get
        End Property

        Public ReadOnly Property Name1() As String Implements INamed.Name
            Get
                Return Me.Name
            End Get
        End Property

        Public Property StreamControlData() As Byte() Implements DataStream.IStreamConfig.StreamControlData
            Get
                If Not IsNothing(mBarSettings) Then
                    Dim loader As New Modules.ObjectPersistance(Of BarContainerSettingCollection)
                    Dim stream As IO.Stream = Nothing

                    ' Compress and serialise
                    loader.SaveToStreamAndCompress(stream, mBarSettings)

                    ' Save the bytes
                    Dim bytes(stream.Length - 1) As Byte
                    stream.Read(bytes, 0, stream.Length)
                    stream.Close()
                    Return bytes
                Else
                    Return Nothing
                End If
            End Get
            Set(ByVal value As Byte())
                If Not IsNothing(value) AndAlso value.Length > 0 Then
                    Dim loader As New Modules.ObjectPersistance(Of BarContainerSettingCollection)
                    Dim stream As BarContainerSettingCollection = Nothing

                    ' uncompress and deserialise
                    loader.LoadFromStreamAndUnCompress(New IO.MemoryStream(value), stream)

                    If Not IsNothing(stream) Then
                        ' Set the settings and cause a Initialise
                        mBarSettings.Clear()

                        stream.CopyTo(mBarSettings)

                        '' Add old for backward compatability
                        'For Each str As String In mStreamItems
                        '    If Not mBarSettings.Contains(str) Then
                        '        mBarSettings.Add(New BarContainerSetting(str, Color.Blue, True))
                        '    End If
                        'Next

                        mStreamItems.Clear()

                        RefreshItems()
                    End If

                End If
            End Set
        End Property

        Public Property DataRefreshTime() As Integer Implements DataStream.IStreamConfig.DataRefreshTime
            Get
                Return mBarSettings.UpdateRate
            End Get
            Set(ByVal value As Integer)
                mBarSettings.UpdateRate = value
                If value > 0 Then
                    mDataRefreshTimer.Interval = value
                End If
            End Set
        End Property
#End Region


        Private Sub uxMenuConfigureControl_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles uxMenuConfigureControl.Click
            Dim setup As New BarContainerSettingSelector(Me.mBarSettings)

            setup.ShowDialog()

            setup.Dispose()

            Me.RefreshItems()
        End Sub

        Public Event Close(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.Close

        Public Sub RecieveSeek(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveSeek
            Me.RecieveStream(Stream)
        End Sub

        Public ReadOnly Property RecieverType() As DataStream.StreamRecieveType Implements DataStream.IStreamRecieve.RecieverType
            Get
                Return StreamRecieveType.eStreamConsumeOnly
            End Get
        End Property
    End Class
End Namespace
